package org.hcf.utils.file;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;


/**
 * 文件处理赋值函数
 *
 * @version 4.3.2
 * @author CD826
 * @since 4.3.2
 */
public class FileUtils {

    /**
     * 判断一个路径是否存在,如果不存在那么根据参数来确定是否创建
     * @param dirPath 所要判断的路径
     * @param bCreate 如果不存在是否创建
     * @return 存在返回true，否则返回false
     */
    public static boolean isDirExist(String dirPath, boolean bCreate) {
        File dir = new File(dirPath);
        if (dir.exists())
            return true;
        if (bCreate) {
            File parent = dir.getParentFile();
            if(parent.exists()){
                return dir.mkdir();
            }else{
                if(isDirExist(dir.getParent(), bCreate))
                    return dir.mkdir();
                else
                    return false;
            }
        }
        return false;
    }
    /**
     * 创建新文件
     * @param path
     */
    public static void createFile(String path) {
        File file = new File(path);
        isDirExist(file.getParent(),true);
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建新目录
     * @param path
     */
    public static void createDir(String path) {
        isDirExist(path,true);
    }

    /**
     * 剪切文件或者目录到某个指定的路径
     * @param source 源文件或者目录
     * @param target 目标路径
     */
    public static void move(String source, String target) {
        File sourFile = new File(source);
        File tarFile = new File(target);
        if (sourFile.isFile()) {
            if (tarFile.isDirectory()) {
                sourFile.renameTo(tarFile);
            }
        } else {
            copy(source, target);
            delete(source);
        }
    }

    private static void copy(File source, File target) throws IOException {
        if (source.isDirectory()) {
            target.mkdir();
            File[] fs = source.listFiles();
            for (int i = 0; i < fs.length; i++) {
                copy(fs[i], target);
            }
        } else {
            if (target.isDirectory())
                target = new File(target, source.getName());
            InputStream is = new FileInputStream(source);
            OutputStream os = new FileOutputStream(target);
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = is.read(buf)) != -1) {
                os.write(buf, 0, len);
            }
            is.close();
            os.close();
        }
    }

    /**
     * 拷贝文件或者目录到某个指定的路径
     *
     * @param source
     *            源文件或者目录
     * @param target
     *            目标路径
     * @return 成功标示
     */
    public static boolean copy(String source, String target) {
        File sour = new File(source);
        File tar = new File(target);
        try {
            copy(sour, tar);
            return (true);
        } catch (IOException e) {
            e.printStackTrace();
            return (false);
        }
    }

    private static void delete(File file) {
        if (file.isDirectory()) {
            File[] fs = file.listFiles();
            for (int i = 0; i < fs.length; i++) {
                delete(fs[i]);
            }
            file.delete();
        } else {
            file.delete();
        }
    }

    /**
     * 删除一个文件或者目录
     * @param path
     */
    public static void delete(String path) {
        File file = new File(path);
        delete(file);
    }

    /**
     * 压缩文件或者目录到指定的路径
     * @param zipFileName  目标路径
     * @param inputPath  被压缩的文件或者目录
     */
    public static void zip(String zipFileName, String inputPath) {
        File inputFile = new File(inputPath);
        ZipOutputStream out;
        try {
            out = new ZipOutputStream(new FileOutputStream(zipFileName));
            zip(out, inputFile, inputFile.getName());
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void zip(ZipOutputStream out, File f, String base) throws Exception {
        if (f.isDirectory()) {
            File[] fs = f.listFiles();
            base += "/";
            out.putNextEntry(new ZipEntry(base)); // 生成相应的目录
            for (int i = 0; i < fs.length; i++) {
                // 对本目录下的所有文件对象递归调用本方法
                zip(out, fs[i], base + fs[i].getName());
            }
        } else {
            out.putNextEntry(new ZipEntry(base));
            InputStream is = new FileInputStream(f);
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = is.read(buf)) != -1) {
                out.write(buf, 0, len);
            }
            is.close();
        }
    }

    /**
     *
     * 解压缩zip文件到指定的路径
     *
     * @param zipFile zip格式压缩文件
     * @param desPath 目标路径
     */
    public static void unzip(String zipFile, String desPath) {
        // 建立输出流，用于将从压缩文件中读出的文件流写入到磁盘
        OutputStream out = null;
        // 建立输入流，用于从压缩文件中读出文件
        ZipInputStream is;
        try {
            is = new ZipInputStream(new FileInputStream(zipFile));
            ZipEntry entry = null;
            while ((entry = is.getNextEntry()) != null) {
                File f = new File(desPath + "\\\\" + entry.getName());
                if (entry.isDirectory()) {
                    f.mkdir();
                } else {
                    // 根据压缩文件中读出的文件名称新建文件
                    out = new FileOutputStream(f);
                    byte[] buf = new byte[1024];
                    int len = 0;
                    while ((len = is.read(buf)) != -1) {
                        out.write(buf, 0, len);
                    }
                    out.close();
                }
            }
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 格式化文件大小
     *
     * @param fileSize
     *            文件的原大小，以Byte计算
     * @return
     */
    public static String calcFileSize(int fileSize) {
        NumberFormat f = new DecimalFormat("#.00");
        double size = fileSize;
        size /= 1024;
        if (size > 1024) {
            size /= 1024;
        } else {
            return f.format(size) + "KB";
        }

        if (size > 1024) {
            size /= 1024;
            return f.format(size) + "GB";
        } else {
            return f.format(size) + "MB";
        }
    }

    private static Pattern pex = Pattern.compile("\\{(.*?)\\}");

    public static File[] listSortedFiles(List list) throws Exception {
        FileWrapper[] fileWrappers = new FileWrapper[list.size()];
        for (int i = 0; i < list.size(); i++) {
            fileWrappers[i] = new FileWrapper((File) list.get(i));
        }
        Arrays.sort(fileWrappers);
        File[] sortedFiles = new File[list.size()];
        for (int i = 0; i < list.size(); i++) {
            sortedFiles[i] = fileWrappers[i].getFile();
        }
        return sortedFiles;
    }

    // 删除文件夹下所有内容，包括此文件夹
    public static void loadAll(File f, List fileList) throws IOException {
        if (!f.exists())// 文件夹不存在不存在
            throw new IOException("指定目录不存在:" + f.getName());
        if (f.isFile()) {
            return;
        }
        File[] files = f.listFiles();
        for (int i = 0; i < files.length; i++) {
            if (files[i].isDirectory()) {
                loadAll(files[i], fileList);
            } else if (files[i].isFile()) {
                fileList.add(files[i]);
            } else {

            }
        }
    }



    public static String getClassName(File file) throws Exception {
        String fileName = file.getName();
        String className = "";
        String packageName = "";
        String fullName = "";
        packageName = file.getParentFile().getName().replaceAll("package", "");
        if (packageName.startsWith(".")) {
            packageName = packageName.substring(1);
        }
        Matcher mex = pex.matcher(fileName);
        if (mex.find()) {
            className = mex.group(1);
        } else {
            throw new Exception("文件名解析错误,忽略导入.(" + className + ")");
        }
        fullName = packageName + "." + className;
        return fullName;
    }


}

class FileWrapper implements Comparable {
    /** File */
    private File file;

    public FileWrapper(File file) {
        this.file = file;
    }

    public int compareTo(Object obj) {
        FileWrapper castObj = (FileWrapper) obj;

        if (this.file.getName().compareTo(castObj.getFile().getName()) > 0) {
            return 1;
        } else if (this.file.getName().compareTo(castObj.getFile().getName()) < 0) {
            return -1;
        } else {
            return 0;
        }
    }

    public File getFile() {
        return this.file;
    }
}